package ws.very.util.lang

import java.util.concurrent.ExecutorService

object Using {
  type CloseAble = {def close}
  type ShutdownAble = {def shutdown}

  @inline
  def apply[R, S](rs: S) =
    (doing: S => R) =>
      try
        doing(rs)
      finally {
        matchAction(rs)
      }

  private def matchAction[S](use: S): Unit = use match {
    case p: ExecutorService => p.shutdown
    case a: AutoCloseable => a.close()
    case c: Closeable => c.close


    case rss: Product =>
      rss.productIterator.foreach {
        matchAction
      }

    case c: CloseAble => c.close

    case s: ShutdownAble => s.shutdown
  }

  @inline
  def executorService[R](rs: ExecutorService)(doing: ExecutorService => R) =
    try
      doing(rs)
    finally
      rs.shutdown

  @inline
  def closeable[R, S <: Closeable](rs: S)(doing: S => R) =
    try
      doing(rs)
    finally
      rs.close

}

